﻿
//#define VERBOSE

using System;
using System.Net.NetworkInformation;
using System.Management;

class Program
{
  static void Main(string[] args)
  {

    NetworkInterface[] interfaces = NetworkInterface.GetAllNetworkInterfaces();

    while ( wirelessObject == null )
    {
      NetworkInterface wirelessInterface =
        FindInterfaceByType(NetworkInterfaceType.Wireless80211, interfaces);

      if ( wirelessInterface == null )
      {
        Console.WriteLine("Please enable your wireless adapter and press any key.");
        Console.ReadKey();
        interfaces = NetworkInterface.GetAllNetworkInterfaces();
      }
      else
      {
        wirelessObject = FindNetByName(wirelessInterface.Description);
        if ( wirelessObject == null )
          Console.WriteLine("WMI Error: Unable to find adapter {0}", wirelessInterface.Name);
      }
    }

    while ( ethernetObject == null )
    {
      NetworkInterface ethernetInterface =
        FindInterfaceByType(NetworkInterfaceType.Ethernet, interfaces);

      if ( ethernetInterface == null )
      {
        Console.WriteLine("Please enable your ethernet adapter and press any key.");
        Console.ReadKey();
        interfaces = NetworkInterface.GetAllNetworkInterfaces();
      }
      else
      {
        ethernetObject = FindNetByName(ethernetInterface.Description);
        if ( ethernetObject == null )
          Console.WriteLine("WMI Error: Unable to find adapter {0}", ethernetInterface.Name);
      }
    }

    #if VERBOSE
      WriteWMINetInformation(ethernetObject);
      Console.WriteLine();
      WriteWMINetInformation(wirelessObject);
      Console.WriteLine();
    #endif

    OnAddressChanged(null, null);

    NetworkChange.NetworkAddressChanged += OnAddressChanged;

      // To prevent the process from exiting immediately
    Console.WriteLine("Press Enter to Quit...\n");
    Console.ReadLine();
  }

  static ManagementObject FindNetByName(string name)
  {
    ManagementClass adapterManager = new ManagementClass("Win32_NetworkAdapter");
    ManagementObjectCollection adapterCollection = adapterManager.GetInstances();
    foreach (ManagementObject adapter in adapterCollection)
    {
      object adapterMAC = adapter["Name"];
      if ( adapterMAC != null && adapterMAC.ToString() == name )
        return adapter;
    }

    return null;
  }

  static NetworkInterface FindInterfaceByType(NetworkInterfaceType type, NetworkInterface[] nics)
  {
    if ( nics == null )
      nics = NetworkInterface.GetAllNetworkInterfaces();

    foreach ( NetworkInterface adapter in nics )
    {
      if ( adapter.NetworkInterfaceType == type )
        return adapter;
    }
    return null;
  }

  static UInt32 EnableMO(ManagementObject m)
  {
    return Convert.ToUInt32(m.InvokeMethod("Enable", new object[0]));
  }

  static UInt32 DisableMO(ManagementObject m)
  {
    return Convert.ToUInt32(m.InvokeMethod("Disable", new object[0]));
  }

  static void OnAddressChanged(object sender, EventArgs e)
  {
    // Re-check the current network status

    ethernetObject.Get();
    wirelessObject.Get();

    #if VERBOSE
      Console.WriteLine("Address change detected...\n");
      WriteWMINetInformation(ethernetObject);
      Console.WriteLine();
      WriteWMINetInformation(wirelessObject);
      Console.WriteLine();
    #endif

    if ( ethernetObject == null )
    {
      Console.WriteLine("ERROR: No ethernet adapter detected.");
      return;
    }

    if ( wirelessObject == null )
    {
      Console.WriteLine("ERROR: No wireless adapter detected.");
      return;
    }

    UInt16 ethernetStatus = (UInt16)ethernetObject["NetConnectionStatus"];
    UInt16 wirelessStatus = (UInt16)wirelessObject["NetConnectionStatus"];

    if ( ethernetStatus == (UInt16)NetConnectionStatus.Code.Connected &&
         wirelessStatus != (UInt16)NetConnectionStatus.Code.Disconnected )
    {
      #if VERBOSE
        Console.WriteLine("Disabling the wireless adapter.");
      #endif
      UInt32 code = DisableMO(wirelessObject);
      if (code == 0)
        Console.WriteLine("Disabled the adapter {0}", wirelessObject["Name"]);
      else
        Console.WriteLine("ERROR: Failed to disable the adapter {0} with code {1}\n", wirelessObject["Name"], code);
    }
    else if ( ethernetStatus == (UInt16)NetConnectionStatus.Code.MediaDisconnected &&
              wirelessStatus == (UInt16)NetConnectionStatus.Code.Disconnected )
    {
      #if VERBOSE
        Console.WriteLine("Enabling the wireless adapter.");
      #endif
      UInt32 code = EnableMO(wirelessObject);
      if ( code == 0 )
        Console.WriteLine("Enabled the adapter {0}", wirelessObject["Name"]);
      else
        Console.WriteLine("ERROR: Failed to enable the adapter {0} with code {1}\n", wirelessObject["Name"], code);
    }
  }

  static void WriteInterfaceInformation(NetworkInterface adapter)
  {
    Console.WriteLine(adapter.Description);
    Console.WriteLine(String.Empty.PadLeft(adapter.Description.Length, '='));
    Console.WriteLine("  State ................................... : {0}", adapter.OperationalStatus);
    Console.WriteLine("  Interface type .......................... : {0}", adapter.NetworkInterfaceType);
    Console.WriteLine("  Physical Address ........................ : {0}", adapter.GetPhysicalAddress());
    Console.WriteLine("  Is receive only.......................... : {0}", adapter.IsReceiveOnly);
    Console.WriteLine("  Multicast................................ : {0}", adapter.SupportsMulticast);
    Console.WriteLine();
  }

  static void WriteWMINetInformation(ManagementObject adapter)
  {
    string name = adapter["Name"].ToString();
    Console.WriteLine(name);
    Console.WriteLine(string.Empty.PadLeft(name.Length, '='));
    Console.WriteLine("  Adapter Type ............................ : {0}", adapter["AdapterType"]);
    Console.WriteLine("  Enabled ................................. : {0}", adapter["NetEnabled"]);
    Console.WriteLine("  Physical Address ........................ : {0}", adapter["MACAddress"]);
    Console.WriteLine("  Connection Status ....................... : {0}",
      new NetConnectionStatus((UInt16)adapter["NetConnectionStatus"]));
  }

  static void WritePhysicalWMIInformation()
  {
    Console.WriteLine("Using Windows Management Instrumentation (WMI)");
    Console.WriteLine("==============================================");
    Console.WriteLine();

    ManagementClass adapterManager = new ManagementClass("Win32_NetworkAdapter");
    ManagementObjectCollection adapterCollection = adapterManager.GetInstances();

    foreach (ManagementObject adapter in adapterCollection)
    {
      if (adapter["PhysicalAdapter"].ToString() == "False")
        continue;

      WriteWMINetInformation(adapter);

      Console.WriteLine();
    }
  }

  static ManagementObject wirelessObject;
  static ManagementObject ethernetObject;

}

class NetConnectionStatus
{
  public NetConnectionStatus(UInt16 code)
  {
    this.code = code;
  }

  public override string ToString()
  {
    switch ( code )
    {
      case 0:
        return "Disconnected";
      case 1:
        return "Connecting";
      case 2:
        return "Connected";
      case 3:
        return "Disconnecting";
      case 4:
        return "Hardware Not Present";
      case 5:
        return "Hardware Not Enabled";
      case 6:
        return "Hardware Malfunction";
      case 7:
        return "Media Disconnected";
      case 8:
        return "Authenticating";
      case 9:
        return "Authentication Succeeded";
      case 10:
        return "Authentication Failed";
      case 11:
        return "Invalid Address";
      case 12:
        return "Credentials Required";
      default:
        return null;
    }
  }

  public enum Code : ushort
  {
    Disconnected = 0,
    Connecting = 1,
    Connected = 2,
    Disconnecting = 3,
    HardwareNotPresent = 4,
    HardwareNotEnabled = 5,
    HardwareMalfunction = 6,
    MediaDisconnected = 7,
    Authenticating = 8,
    AuthenticationSucceeded = 9,
    AuthenticationFailed = 10,
    InvalidAddress = 11,
    CredentialsRequired = 12
  }

  UInt16 code;
}

